package com.es.twilio.emulator.parser;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;

import org.jdom.Attribute;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;

import com.es.twilio.emulator.api.Parser;
import com.twilio.sdk.verbs.Conference;
import com.twilio.sdk.verbs.Dial;
import com.twilio.sdk.verbs.Gather;
import com.twilio.sdk.verbs.Hangup;
import com.twilio.sdk.verbs.Number;
import com.twilio.sdk.verbs.Pause;
import com.twilio.sdk.verbs.Play;
import com.twilio.sdk.verbs.Record;
import com.twilio.sdk.verbs.Redirect;
import com.twilio.sdk.verbs.Say;
import com.twilio.sdk.verbs.TwiMLException;
import com.twilio.sdk.verbs.TwiMLResponse;
import com.twilio.sdk.verbs.Verb;

public class ParserImpl implements Parser {
	
	
	@Override
	public TwiMLResponse parseXML(InputStream ins) throws TwiMLException {
		try {
			SAXBuilder builder = new SAXBuilder();
			Document doc = builder.build(ins);
			Verb v = getVerb(doc.getRootElement());
			if (v instanceof TwiMLResponse) {
				return (TwiMLResponse)v;	
			} else {
				throw new TwiMLException("Error parsing the document");
			}
		} catch (JDOMException e) {
			throw new TwiMLException(e.getMessage());
		} catch (NullPointerException e) {
			throw new TwiMLException(e.getMessage());
		} catch (IOException e) {
			throw new TwiMLException(e.getMessage());
		}
	}
	private Verb newVerb(Element e) {
		Verb v = null;
		String verbName = e.getName();
		if (verbName.equals(TwiMLResponse.V_CONFERENCE)) {
			v = new Conference(e.getText());
		} else if (verbName.equals(TwiMLResponse.V_DIAL)) {
			v = new Dial(e.getText());
		} else if (verbName.equals(TwiMLResponse.V_GATHER)) {
			v = new Gather();
		} else if (verbName.equals(TwiMLResponse.V_HANGUP)) {
			v = new Hangup();
		} else if (verbName.equals(TwiMLResponse.V_NUMBER)) {
			v = new Number(e.getText());
		} else if (verbName.equals(TwiMLResponse.V_PAUSE)) {
			v = new Pause();
		} else if (verbName.equals(TwiMLResponse.V_PLAY)) {
			v = new Play(e.getText());
		} else if (verbName.equals(TwiMLResponse.V_RECORD)) {
			v = new Record();
		} else if (verbName.equals(TwiMLResponse.V_REDIRECT)) {
			v = new Redirect(e.getText());
		} else if (verbName.equals(TwiMLResponse.V_RESPONSE)) {
			v = new TwiMLResponse();
		} else /*if (verbName.equals(TwiMLResponse.V_SAY))*/ {
			v = new Say(e.getText());
		}
		if (v== null ) {
			throw new UnsupportedOperationException("Have not implemented this verb yet: " +verbName);
		}
		return v;
	}
	@SuppressWarnings("unchecked")
	private Verb getVerb(Element e) throws TwiMLException {
		Verb verb = newVerb(e);
		
		List<Attribute> attributes = e.getAttributes();
		for (Attribute attribute : attributes) {
			verb.set(attribute.getName(), attribute.getValue());
		}
		
		List<Element> children = e.getChildren();
		for (Element element : children) {
			verb.append(getVerb(element));
		}

		return verb;
	}
}
